﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RzCorportativo.Lib
{
    public class Indicacao
    {
        public long IndicacaoId { get; set; }
        public DateTime DataCadastro { get; set; }
        /// <summary>
        /// Resultado final após a avaliação do candidato
        /// 0 - não cadastrado
        /// 1 - aprovado
        /// 2 - reprovado
        /// 3 - indicação cancelada
        /// </summary>
        public short ResultadoFinal { get; set; }
        /// <summary>
        ///  Status da indicação 
        ///  0 - não cadastrado
        ///  1 - indicação ativa
        ///  2 - indicação aceita pelo candidato
        ///  3 - indicação recusada pelo candidato
        ///  4 - inidicação cancelada
        /// </summary>
        public short Status { get; set; }
        public long UsuarioIndicadoId { get; set; }
        public long VagaId { get; set; }
        public Usuario UsuarioIndicado { get; set; }
        public bool IsNew { get { return DataCadastro == null || DataCadastro == DateTime.MinValue; } }
        
        public Vaga Vaga { get; set; }
        public long UsuarioIndicadorId { get; set; }
        List<Lib.Feedback> FeedBacks = new List<Feedback>();

        public bool Salvar()
        {
            bool result = false;
            DataAccess.Transaction.Begin(context =>
            {
                DataAccess.Indicacao indicacao = null;
                if (this.IsNew)
                {
                    this.DataCadastro = DateTime.Now.Date;
                    indicacao = this.Insert(context);
                }
                else
                    indicacao = this.Update(context);
                if(this.FeedBacks.Count > 0)
                    foreach (var item in this.FeedBacks)
                    {
                        item.UsuarioIndicadoId = this.UsuarioIndicadoId;
                        if (!item.Salvar()) 
                            throw new Exception("Falha ao tentar salvar o feedback");
                    }
                return result = true;                
            }).OnError(ex =>
            {
                throw ex;
            }).OnSuccess(() =>
            {
                result = true;
            });
            return result;
        }

        private DataAccess.Indicacao Update(DataAccess.SistemaCurricularEntities context)
        {
            return this.CreateModel(context);
        }

        private DataAccess.Indicacao Insert(DataAccess.SistemaCurricularEntities context)
        {
            var model = this.CreateModel(context, true);
            context.AddToIndicacao(model);
            return model;
        }

        private DataAccess.Indicacao CreateModel(DataAccess.SistemaCurricularEntities context, bool forceIsNew = false)
        {
            DataAccess.Indicacao indicacao = null;
            if (this.IsNew || forceIsNew)
            {
                indicacao = new DataAccess.Indicacao();
                indicacao.DataIndicacao = this.DataCadastro;
            }
            else
            {
                indicacao = context.Indicacao.FirstOrDefault(f => f.VagaId == this.VagaId && this.UsuarioIndicadoId == f.UsuarioIndicadoId && this.DataCadastro == f.DataIndicacao);
                if (indicacao == null)
                    throw new Exception("Código de vaga ou código de usuário indicado inválido");
                this.UsuarioIndicadorId = indicacao.UsuarioIndicadorId;
                this.DataCadastro = indicacao.DataIndicacao;
            }
            indicacao.UsuarioIndicadorId = this.UsuarioIndicadorId;
            indicacao.ResultadoFinal = this.ResultadoFinal;
            indicacao.Status = this.Status;
            indicacao.UsuarioIndicadoId = this.UsuarioIndicadoId;
            indicacao.VagaId = this.VagaId;
            return indicacao;
        }

        internal Lib.Indicacao Create(DataAccess.Indicacao model)
        {
            if (model == null)
                return null;
            Lib.Indicacao item = new Indicacao();
            item.UsuarioIndicadorId = model.UsuarioIndicadorId;
            item.DataCadastro = model.DataIndicacao;
            item.ResultadoFinal = model.ResultadoFinal;
            item.Status = model.Status;
            item.UsuarioIndicadoId = model.UsuarioIndicadoId;
            item.UsuarioIndicado = new Usuario().Create(model.Usuario);
            item.VagaId = model.VagaId;
            item.Vaga = new Vaga().Create(model.Vaga);
            return item;
        }

        public static List<Lib.Indicacao> Listar(Lib.Indicacao indicao) {
            if (indicao == null)
                indicao = new Indicacao();
            bool naoValidaData = indicao.DataCadastro.Date == DateTime.MinValue.Date;
            var model = indicao.CreateModel(null, true);
            model.Usuario = new DataAccess.Usuario();
            if (indicao.UsuarioIndicado != null)
            {
                model.Usuario.Cpf = indicao.UsuarioIndicado.Cpf ?? string.Empty;
                model.Usuario.Nome = indicao.UsuarioIndicado.Nome ?? string.Empty;
                model.Usuario.UsuarioId = indicao.UsuarioIndicado.UsuarioId;
            }
            model.Vaga = new DataAccess.Vaga();
            if (indicao.Vaga != null)
            {
                model.Vaga.CargoId = indicao.Vaga.CargoId;
                model.Vaga.UsuarioRepresentanteId = indicao.Vaga.UsuarioId;
                model.Vaga.Status = indicao.Vaga.Status;
            }
            DataAccess.SistemaCurricularEntities entity = new DataAccess.SistemaCurricularEntities();
            var factory = new Lib.Indicacao();
            var Usuario = model.Usuario;

            return entity.Indicacao.Where(w => (
                    model.VagaId == 0 || model.VagaId == w.VagaId
                ) && (
                    naoValidaData || model.DataIndicacao == w.DataIndicacao
                ) && (
                    model.ResultadoFinal == 0 || model.ResultadoFinal == w.ResultadoFinal
                ) && (
                    model.Status == 0 || model.Status == w.Status
                ) && (
                    (model.UsuarioIndicadoId == 0 || model.UsuarioIndicadoId == w.UsuarioIndicadoId) &&
                    (model.Usuario.Nome == null || model.Usuario.Nome == "" || w.Usuario.Nome.Contains(model.Usuario.Nome)) &&
                    (model.Usuario.Cpf == null || model.Usuario.Cpf == "" || model.Usuario.Cpf == w.Usuario.Cpf)
                ) && (
                    (model.Vaga.CargoId == 0 || model.Vaga.CargoId == w.Vaga.CargoId) &&
                    (model.Vaga.Status == 0 || model.Vaga.Status == w.Vaga.Status)
                )).ToList().Select(s => factory.Create(s)).ToList();
        }

        public void AddFeedback(Feedback feed)
        {
            this.FeedBacks.Add(feed);
        }
    }
}
